#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <cstring>

// 信号处理函数：回收所有已退出的子进程
// 注意：信号处理函数中应尽量使用异步信号安全的函数
void sigchld_handler(int signum)
{
    // 循环回收所有已退出的子进程（避免信号合并导致漏收）
    while (true)
    {
        int status;                                      // 用于存储子进程退出状态
        pid_t child_pid = waitpid(-1, &status, WNOHANG); // 非阻塞等待任意子进程

        if (child_pid == -1)
        {
            // 错误处理：区分"无子进程可回收"和真正的错误
            if (errno == ECHILD)
            {
                // 正常情况：所有子进程已被回收
                const char *msg = "所有子进程已回收完毕\n";
                write(STDOUT_FILENO, msg, strlen(msg)); // write是异步信号安全的
                break;
            }
            else
            {
                // 异常错误：输出错误信息
                const char *err_msg = "waitpid出错: ";
                write(STDOUT_FILENO, err_msg, strlen(err_msg));
                write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
                write(STDOUT_FILENO, "\n", 1);
                break;
            }
        }
        else if (child_pid == 0)
        {
            // 暂时没有已退出的子进程，退出循环
            break;
        }
        else
        {
            // 成功回收一个子进程，解析退出状态
            if (WIFEXITED(status))
            {
                // 子进程正常退出
                char buf[128];
                snprintf(buf, sizeof(buf), "子进程 %d 正常退出，退出码: %d\n",
                         child_pid, WEXITSTATUS(status));
                write(STDOUT_FILENO, buf, strlen(buf));
            }
            else if (WIFSIGNALED(status))
            {
                // 子进程被信号终止
                char buf[128];
                snprintf(buf, sizeof(buf), "子进程 %d 被信号终止，信号编号: %d\n",
                         child_pid, WTERMSIG(status));
                write(STDOUT_FILENO, buf, strlen(buf));
            }
        }
    }

    // 信号处理完成提示（使用write保证安全）
    char sig_msg[64];
    snprintf(sig_msg, sizeof(sig_msg), "父进程捕获到SIGCHLD信号（编号: %d）\n", signum);
    write(STDOUT_FILENO, sig_msg, strlen(sig_msg));
}

int main()
{
    // 注册SIGCHLD信号处理函数
    // SIGCHLD信号：子进程终止或停止时触发
    // if (signal(SIGCHLD, sigchld_handler) == SIG_ERR)
    // {
    //     std::cerr << "注册信号处理函数失败: " << strerror(errno) << std::endl;
    //     return 1;
    // }

    if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
    {
        std::cerr << "注册信号处理函数失败: " << strerror(errno) << std::endl;
        return 1;
    }

    // 创建10个子进程
    for (int i = 0; i < 10; i++)
    {
        pid_t cid = fork();

        if (cid == -1)
        {
            // fork失败处理
            std::cerr << "创建子进程失败: " << strerror(errno) << std::endl;
            return 1;
        }
        else if (cid == 0)
        {
            // 子进程逻辑
            // 输出启动信息（子进程中使用cout需注意缓冲问题）
            std::cout << "子进程 " << getpid() << " 启动" << std::endl;
            // 子进程休眠3秒模拟工作
            sleep(3);
            // 退出并返回状态码3
            exit(3);
        }
        // 父进程继续循环创建下一个子进程
    }

    // 父进程主循环：模拟持续工作
    while (true)
    {
        printf("父进程正在执行任务...\n");
        sleep(1); // 每秒输出一次
    }

    return 0;
}